package com.molichuxing.services.business.service.impl;


import com.molichuxing.framework.dto.Paged;
import com.molichuxing.framework.exception.BizException;
import com.molichuxing.framework.utils.ObjectCastUtil;
import com.molichuxing.services.business.dto.request.modify.StoreDeviceBizModifyDto;
import com.molichuxing.services.business.dto.response.DealerBizDto;
import com.molichuxing.services.business.dto.response.DeviceInfoBizDto;
import com.molichuxing.services.business.dto.response.StoreInfoBizDto;
import com.molichuxing.services.business.service.DeviceBizService;
import com.molichuxing.services.business.service.StoreBizService;
import com.molichuxing.services.infrastructure.convertor.Convert;
import com.molichuxing.services.infrastructure.dto.request.modify.DeviceModifyDto;
import com.molichuxing.services.infrastructure.dto.response.*;
import com.molichuxing.services.infrastructure.service.*;
import com.molichuxing.services.property.DeviceParamDictTypeEnum;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
 * <p>
 * 设备组合 服务实现类
 * </p>
 *
 * @author
 * @since 2019-10-30
 */
@Service("deviceBizService")
public class DeviceBizServiceImpl implements DeviceBizService {

    @Autowired
    DeviceService deviceService;
    @Autowired
    StoreDeviceService storeDeviceService;
    @Autowired
    StoreService storeService;
    @Autowired
    DeviceParamDictService deviceParamDictService;
    @Autowired
    DealerService dealerService;
    @Autowired
    StoreBizService storeBizService;

    /**
     * 通过cpu获取终端信息
     *
     * @param cpu
     * @return
     * @throws Exception
     */
    @Override
    public DeviceInfoBizDto getDeviceInfo(String cpu) throws Exception {
        DeviceDto deviceDto = deviceService.getDeviceByCpu(cpu);
        if (null == deviceDto) {
            return null;
        }

        DeviceInfoBizDto deviceInfoBizDto = Convert.toDeviceInfoBizDto(deviceDto);
        Integer deviceId = deviceDto.getDeviceId();
        Integer storeId = storeDeviceService.getStoreIdByDevice(deviceId);
        if (null == storeId) {
            return deviceInfoBizDto;
        }

        StoreDto storeDto = storeService.getStoreById(storeId);
        if (null == storeDto) {
            return deviceInfoBizDto;
        }
        deviceInfoBizDto.setStoreId(storeDto.getStoreId());
        deviceInfoBizDto.setStoreName(storeDto.getShortName());

        String terminalVersionCode = deviceDto.getTerminalVersionCode();
        String channelVersionCode = deviceDto.getChannelVersionCode();
        DeviceParamDictDto terminalDto = deviceParamDictService.getByParamKey(terminalVersionCode, DeviceParamDictTypeEnum.TERMINAL_VERSION.getValue());
        if (terminalDto != null) {
            String paramValue = terminalDto.getParamValue();
            deviceInfoBizDto.setTerminalVersionValue(paramValue);
        }

        DeviceParamDictDto channelDto = deviceParamDictService.getByParamKey(channelVersionCode, DeviceParamDictTypeEnum.CHANNEL_NAME.getValue());
        if (channelDto != null) {
            String paramValue = channelDto.getParamValue();
            deviceInfoBizDto.setChannelVersionValue(paramValue);
        }
        return deviceInfoBizDto;
    }

    /**
     * 终端
     *
     * @param map
     * @return
     */
    @Override
    public DeviceInfoBizDto getDeviceStatus(Map<String, Object> map) {
        String cpu = ObjectCastUtil.castString(map.get("cpu"));
        String appVersion = ObjectCastUtil.castString(map.get("appVersion"));
        String appPatchVersion = ObjectCastUtil.castString(map.get("appPatchVersion"));
        DeviceDto deviceDto = deviceService.getDeviceByCpu(cpu);
        if (null == deviceDto) {
            throw new BizException("非有效设备");
        }

        if (StringUtils.isNotBlank(appVersion) || StringUtils.isNotBlank(appPatchVersion)) {
            DeviceModifyDto deviceModifyDto = new DeviceModifyDto();
            deviceModifyDto.setId(deviceDto.getDeviceId());
            if (StringUtils.isNotBlank(appVersion)) {
                deviceModifyDto.setAppVersion(appVersion);
            }
            if (StringUtils.isNotBlank(appPatchVersion)) {
                deviceModifyDto.setAppPatchVersion(appPatchVersion);
            }
            deviceService.modifyDevice(deviceModifyDto);
        }

        return Convert.toDeviceInfoBizDto(deviceDto);
    }

    /**
     * 设备
     *
     * @param map
     * @param pageNum
     * @param pageSize
     * @return
     * @throws Exception
     */
    @Override
    public Paged<DeviceInfoBizDto> getDevicePage(Map<String, Object> map, Integer pageNum, Integer pageSize) throws Exception {
        getDeviceIdList(map);

        Paged<DeviceDto> devicePage = deviceService.getDevicePage(map, pageNum, pageSize);
        if (null == devicePage) {
            return new Paged<DeviceInfoBizDto>();
        }
        List<DeviceDto> deviceDtoList = devicePage.getList();
        if (null == deviceDtoList || deviceDtoList.size() == 0) {
            return new Paged<DeviceInfoBizDto>();
        }

        List<Integer> deviceIdList = new ArrayList<>();
        for (DeviceDto deviceDto : deviceDtoList) {
            deviceIdList.add(deviceDto.getDeviceId());
        }

        List<StoreDeviceDto> storeDeviceList = storeDeviceService.getStoreIdsByDevice(deviceIdList);
        List<StoreDto> storeDtoList = null;
        if (storeDeviceList != null && storeDeviceList.size() > 0) {
            List<Integer> storeIdList = new ArrayList<>();
            for (StoreDeviceDto storeDeviceDto : storeDeviceList) {
                storeIdList.add(storeDeviceDto.getStoreId());
            }
            storeDtoList = storeService.getStoreListByIds(storeIdList);
        }
        List<DealerDto> dealerDtoList = null;
        if (storeDtoList != null && storeDtoList.size() > 0) {
            List<Integer> storeIdList = new ArrayList<>();
            for (StoreDeviceDto storeDeviceDto : storeDeviceList) {
                storeIdList.add(storeDeviceDto.getStoreId());
            }
            dealerDtoList = dealerService.getDealerDtoListByIds(storeIdList);
        }

        List<DeviceInfoBizDto> pagedReturnList = getPagedReturnList(deviceDtoList, storeDeviceList, storeDtoList, dealerDtoList);
        return new Paged<DeviceInfoBizDto>(pagedReturnList, devicePage.getTotal(), pageSize);
    }

    private void getDeviceIdList(Map<String, Object> map) throws Exception {
        Integer storeId = ObjectCastUtil.castInteger(map.get("storeId"));
        Integer dealerId = ObjectCastUtil.castInteger(map.get("dealerId"));
        if (dealerId != null) {
            List<Integer> storeIdList = storeService.getStoreIdByDealer(dealerId);
            List<Integer> deviceIdList = storeDeviceService.getDeviceIdByStoreIds(storeIdList);
            if (deviceIdList == null || deviceIdList.size() < 1) {
                deviceIdList = new ArrayList<>();
                deviceIdList.add(0);
            }
            map.put("deviceIdList", deviceIdList);
        }

        if (storeId != null) {
            List<Integer> deviceIdList = storeDeviceService.getDeviceIdByStoreId(storeId);
            if (deviceIdList == null || deviceIdList.size() < 1) {
                deviceIdList = new ArrayList<>();
                deviceIdList.add(0);
            }
            map.put("deviceIds", deviceIdList);
        }

    }

    private List<DeviceInfoBizDto> getPagedReturnList(List<DeviceDto> deviceDtoList,
                                                      List<StoreDeviceDto> storeDeviceList, List<StoreDto> storeDtoList,
                                                      List<DealerDto> dealerDtoList) throws Exception {
        List<DeviceInfoBizDto> bizDtoList = Convert.toDeviceInfoBizDtoLIst(deviceDtoList);
        if (null == storeDeviceList || storeDeviceList.size() < 1) {
            return bizDtoList;
        }
        Map<Integer, StoreDto> storeMap = new HashMap<>();
        Map<Integer, DealerDto> dealerMap = new HashMap<>();
        if (storeDtoList != null && storeDtoList.size() > 0) {
            storeMap = storeDtoList.stream().collect(Collectors.toMap(StoreDto::getStoreId, a -> a, (k1, k2) -> k1));
        }
        if (dealerDtoList != null && dealerDtoList.size() > 0) {
            dealerMap = dealerDtoList.stream().collect(Collectors.toMap(DealerDto::getDealerId, a -> a, (k1, k2) -> k1));
        }

        for (DeviceInfoBizDto deviceInfoBizDto : bizDtoList) {
            String terminalVersionCode = deviceInfoBizDto.getTerminalVersionCode();
            DeviceParamDictDto terminalDto = deviceParamDictService.getByParamKey(terminalVersionCode, DeviceParamDictTypeEnum.TERMINAL_VERSION.getValue());
            if (terminalDto != null) {
                String paramValue = terminalDto.getParamValue();
                deviceInfoBizDto.setTerminalVersionValue(paramValue);
            }

            Integer deviceId = deviceInfoBizDto.getDeviceId();
            Map<Integer, StoreDeviceDto> storeDeviceMap = storeDeviceList.stream().collect(Collectors.toMap(StoreDeviceDto::getDeviceId, a -> a, (k1, k2) -> k1));
            StoreDeviceDto storeDeviceDto = storeDeviceMap.get(deviceId);
            if (null == storeDeviceDto) {
                continue;
            }
            Integer storeId = storeDeviceDto.getStoreId();
            if (storeDtoList == null || storeDtoList.size() < 1) {
                continue;
            }
            StoreDto storeDto = storeMap.get(storeId);
            if (null == storeDto) {
                continue;
            }
            deviceInfoBizDto.setStoreId(storeId);
            deviceInfoBizDto.setStoreName(storeDto.getShortName());

            if (dealerDtoList == null || dealerDtoList.size() < 1) {
                continue;
            }
            Integer dealerId = storeDto.getDealerId();
            DealerDto dealerDto = dealerMap.get(storeId);
            if (null == dealerDto) {
                continue;
            }
            deviceInfoBizDto.setDealerId(dealerId);
            deviceInfoBizDto.setDealerShortName(dealerDto.getShortName());
        }
        return bizDtoList;
    }

    @Override
    public DeviceInfoBizDto getDeviceStore(Integer deviceId) {
        DeviceInfoBizDto deviceInfoBizDto = new DeviceInfoBizDto();
        DeviceDto deviceDto = deviceService.getDeviceById(deviceId);
        Integer storeId = storeDeviceService.getStoreIdByDevice(deviceId);
        StoreInfoBizDto storeInfo = new StoreInfoBizDto();
        try {
            storeInfo = storeBizService.getStoreInfo(storeId);
        } catch (Exception e) {
            e.printStackTrace();
        }
        deviceInfoBizDto.setCpu(deviceDto.getCpu());
        deviceInfoBizDto.setStoreName(storeInfo.getShortName());
        deviceInfoBizDto.setResponsibleName(storeInfo.getResponsibleName());
        deviceInfoBizDto.setResponsiblePhone(storeInfo.getResponsiblePhone());
        return deviceInfoBizDto;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout = 36000, rollbackFor = Exception.class)
    public Boolean modifyStoreDevice(StoreDeviceBizModifyDto storeDeviceBizModifyDto) throws Exception {
        Boolean storeBoolean = storeDeviceService.modifyStoreDevice(storeDeviceBizModifyDto);
        if (!storeBoolean) {
            return false;
        }
        DeviceModifyDto deviceModifyDto = new DeviceModifyDto();
        deviceModifyDto.setId(storeDeviceBizModifyDto.getDeviceId());
        deviceModifyDto.setTerminalVersionCode(storeDeviceBizModifyDto.getTerminalVersionCode());
        return deviceService.modifyDevice(deviceModifyDto);
    }

}
